package gw

import (
	"gitee.com/deep-sea-tech/ds-go-client/dsregistry"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strconv"
	"strings"
)

// 插件接口，支持转发前和转发后
type Plugin interface {
	Before(w http.ResponseWriter, r *http.Request) error
	After(w http.ResponseWriter, r *http.Request, resp *http.Response) error
}

type Route struct {
	Prefix  string
	Service string
	Plugins []Plugin
}

type Gateway struct {
	routes   []Route
	registry *dsregistry.RedisRegistry
}

func NewGateway(registry *dsregistry.RedisRegistry) *Gateway {
	return &Gateway{
		routes:   []Route{},
		registry: registry,
	}
}

func (g *Gateway) AddRoute(prefix, service string, plugins []Plugin) {
	g.routes = append(g.routes, Route{
		Prefix:  prefix,
		Service: service,
		Plugins: plugins,
	})
}

func (g *Gateway) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	route, matched := g.matchRoute(r.URL.Path)
	if !matched {
		http.Error(w, "Not Found", http.StatusNotFound)
		return
	}

	// 执行 Before 钩子
	for _, p := range route.Plugins {
		if err := p.Before(w, r); err != nil {
			return
		}
	}

	inst, err := g.registry.SelectInstance(route.Service, "roundRobin")
	if err != nil {
		http.Error(w, "Service unavailable", http.StatusServiceUnavailable)
		return
	}

	target := &url.URL{
		Scheme: inst.Protocol,
		Host:   inst.Address + ":" + strconv.Itoa(inst.Port),
	}

	proxy := httputil.NewSingleHostReverseProxy(target)

	// 修改请求路径，去除前缀
	r.URL.Path = strings.TrimPrefix(r.URL.Path, route.Prefix)
	if r.URL.Path == "" {
		r.URL.Path = "/"
	}
	r.Host = target.Host

	// 利用 ModifyResponse 处理 After 钩子
	proxy.ModifyResponse = func(resp *http.Response) error {
		for _, p := range route.Plugins {
			if err := p.After(w, r, resp); err != nil {
				log.Printf("After plugin error: %v", err)
				// 响应处理错误不终止响应，记录日志即可
			}
		}
		return nil
	}

	proxy.ServeHTTP(w, r)
}

func (g *Gateway) matchRoute(path string) (Route, bool) {
	for _, route := range g.routes {
		if strings.HasPrefix(path, route.Prefix) {
			return route, true
		}
	}
	return Route{}, false
}
